﻿


#include <iostream>
#include <vector>
using namespace std;

class Solution
{
public:
    int search(vector<int>& nums, int target)
    {
        int lf = 0, rg = nums.size() - 1;

        while (lf <= rg)
        {
            int mid = lf + ((rg - lf) >> 1);

            if (nums[mid] == target)
                return mid;
            else if (nums[mid] > target)
                rg = mid - 1;
            else
                lf = mid + 1;
        }

        return -1;
    }
};

class Person 
{
public:
    virtual void BuyTicket() { cout << "普通人-全价" << endl; }
};

class Student : public Person 
{
public:
    // 可以省略virtual,因为派生类会继承基类中的BuyTicket虚函数且其虚函数的属性不会改变
    // 不建议省略virtual，不规范
    //void BuyTicket() { cout << "学生-优惠" << endl; }
    virtual void BuyTicket() { cout << "学生-优惠" << endl; }
};

void Func1(Person& ptr)
{
    ptr.BuyTicket();
}

void Func2(Person* ptr)
{
    ptr->BuyTicket();
}

void Test1(void)
{
    Person per;
    Student stu;
    Person* pptr = &per;
    Student* pstu = &stu;

    Func1(per);
    Func1(stu);
    cout << endl;
    Func2(pptr);
    Func2(pstu);
}

class Animal
{
public:
    virtual void animal()
    {
        cout << "animal：animal" << endl;
    }
};

class Dog : public Animal
{
public:
    void animal()
    {
        cout << "狗：汪汪" << endl;
    }
};

class Cat : public Animal
{
public:
    void animal()
    {
        cout << "猫：喵喵" << endl;
    }
};

void Func3(Animal& ani)
{
    ani.animal();
}

void Func4(Animal* ani)
{
    ani->animal();
}

void Test2(void)
{
    Animal ani;
    Dog dog;
    Cat cat;
    Animal* pani = &ani;
    Dog* pdog = &dog;
    Cat* pcat = &cat;

    Func3(ani);
    Func3(dog);
    Func3(cat);
    cout << endl;
    Func4(pani);
    Func4(pdog);
    Func4(pcat);
    cout << endl;
    cout << sizeof(ani) << endl;
    cout << sizeof(dog) << endl;
    cout << sizeof(cat) << endl;
}

class A
{
public:
    virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }
    virtual void test() { func(); }
};

class B : public A
{
public:
    void func(int val = 0) { std::cout << "B->" << val << std::endl; }
};

void Test3(void)
{
    // 派生类B继承了基类A的test()，表明派生类B的对象可以去基类A的类域中查找test()并使用。这个可以突破类域查找规则的语法被解释为了继承
    // 当在A类中时，this指针一定是指向自身类型的A*指针，因此p->test()最终变为在A中由this自动调用func()
    // func已经满足重写/覆盖的要求，且由基类的指针调用，因此满足动态多态的条件
    // 注意重写/覆盖的作用是对函数的【函数体】进行重写，而声明仍然沿用基类中的声明
    B* p = new B;
    p->test();
}

class A1 {};
class B1 : public A1 {};

class Person1
{
public:
    virtual A* BuyTicket()
    {
        cout << "买票-全价" << endl;
        return nullptr;
    }
};

class Student1 : public Person1
{
public:
    virtual A* BuyTicket()
    {
        cout << "买票-打折" << endl;
        return nullptr;
    }
};

void Func5(Person1* ptr)
{
    ptr->BuyTicket();
}

void Test4(void)
{
    Person1 per1;
    Student1 stu1;

    Func5(&per1);
    Func5(&stu1);
}

class AA
{
public:
    //~AA()
    virtual ~AA()
    {
        cout << "~AA()" << endl;
    }
};

class BB : public AA {
public:
    ~BB()
    {
        cout << "~BB()->delete:" << _p << endl;
        delete _p;
    }
protected:
    int* _p = new int[10];
};

// 只有派⽣类Student的析构函数重写了Person的析构函数，下⾯的delete对象调⽤析构函数，才能构成多态，才能保证p1和p2指向的对象正确的调⽤析构函数
void Test5(void)
{
    // 假设基类和派生类的析构没有构成多态,且派生类中有需要额外释放的资源。当手动delete基类对象的指针进行析构时,只会调用基类的析构
    // 但基类的指针既可以指向基类,也可以指向派生类。当派生类中还有需要释放的资源时，该方法就会造成资源泄露，因此必须构成多态
    AA* p1 = new AA;
    AA* p2 = new BB;

    delete p1;
    delete p2;
}

int main()
{
    //Test1();
    //Test2();
    //Test3();
    //Test4();
    Test5();

	return 0;
}